import cgi

from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db
import os, logging, datetime
from google.appengine.ext.webapp import template

appkey = 'ABQIAAAAZJYXK-Ld-mTstzJHt7_KzBQUQcbO9FaM5kTkUQsQG64Twt_yyhS0SgjHS3Ee-v3g_7pWt6hNbLjCIw'

class SuggestedWebsite(db.Model):
    url = db.StringProperty()
    
class Event(db.Model):
    name = db.TextProperty()
    date = db.DateTimeProperty(auto_now_add=False)
    date_source = db.TextProperty()
    place = db.TextProperty()
    latitude = db.FloatProperty()
    longitude = db.FloatProperty()
    url = db.StringProperty()
    problem = db.BooleanProperty(default=False)
    def distanceFrom(self, lat, longt):
        return ( (self.latitude - lat)**2 + \
                 (self.longitude - longt)**2 ) ** 0.5
    # source = Website()

class UserQuery(webapp.RequestHandler):
    def get(self):
        template_values = {'events': [],
                           'lat': 0, 'longt': 0,
                           'place': None, 'loc': '',
                           'radius': 0.5, 'num_found': 0,
                           'more_possible': True}        
        path = os.path.join(
            os.path.dirname(__file__), 'results.html')
        self.response.out.write(
            template.render(path, template_values))           

class Troubleshooter(webapp.RequestHandler):
    def get(self):
        id = cgi.escape(self.request.get('id'))
        e = Event.get(id)
        template_values = {'event':e}
        path = os.path.join(os.path.dirname(__file__), 'troubleshoot.html')
        self.response.out.write(
            template.render(path, template_values))           

class Suggestion(webapp.RequestHandler):
    def post(self):
        url = cgi.escape(self.request.get('url'))
        website = SuggestedWebsite()
        website.url = url
        website.put()
        self.response.out.write('''Thanks for suggesting a new
        website to scan for events!
        The webmaster will review suggestions 
        at, um, some unknown time.''')
    get = post
        
class ProblemReport(webapp.RequestHandler):
    def post(self):
        id = cgi.escape(self.request.get('id'))
        e = Event.get(id)
        e.problem = True
        e.put()
        self.response.out.write('Thank you for reporting an error in the event report.\nThe webmaster will try to repair.')

class Suggestions(webapp.RequestHandler):
    def get(self):
        template_values = {'sites':[]}
        qry = SuggestedWebsite.all()
        for site in qry:
            template_values['sites'].append(site)
        path = os.path.join(
            os.path.dirname(__file__), 'suggestions.html')
        self.response.out.write(
            template.render(path, template_values))           
        
class AllEvents(webapp.RequestHandler):
    def get(self):
        qry = Event.all()
        template_values = {'events':[]}
        for event in qry:
            template_values['events'].append(event)
        
        path = os.path.join(
            os.path.dirname(__file__), 'allEvents.html')
        self.response.out.write(
            template.render(path, template_values))           

class ClearEvents(webapp.RequestHandler):
    def get(self):
        passcode = 'captainmayi'
        self.response.headers['Content-Type'] = 'text/plain'        
        if cgi.escape(self.request.get('passcode')) == passcode:
            offset = 0
            while True:
                q = db.GqlQuery('SELECT * FROM Event LIMIT 50 OFFSET %d' % offset)
                db.delete(q)
                offset += 50
            self.response.out.write('Datastore emptied.')
        else:
            self.response.out.write(cgi.escape(self.request.get('passcode')))
        
class EventResults(webapp.RequestHandler):
    def post(self):
        lat = float(cgi.escape(self.request.get('latitude')) or 0)
        longt = float(cgi.escape(self.request.get('longitude')) or 0)
        place = cgi.escape(self.request.get('place'))
        loc = cgi.escape(self.request.get('loc'))
        radius = float(cgi.escape(self.request.get('radius')) or 0.5)
        num_found_last_time = int(cgi.escape(self.request.get('num_found')) or 0)
        template_values = {'events': [],
                           'lat': lat, 'longt': longt,
                           'place': place, 'loc': loc}
        minDate = datetime.datetime.now() - datetime.timedelta(days=1)
        events = []        
        while (radius < 20) and (len(events) <= num_found_last_time):
            events = []        
            qry = Event.gql('WHERE longitude > :1 AND longitude < :2',
                            longt - radius, longt + radius)
            offset = 0
            results = qry.fetch(limit=50, offset=0)        
            while results:
                # Yes, I KNOW this is an insane way to assemble the result set.
                # GAE doesn't permit any of the sane ways.
                events.extend(e for e in results if e.date > minDate
                              and e.distanceFrom(lat, longt) < radius)
                offset += 50
                results = qry.fetch(limit=50, offset=offset)
            radius *= 2
        events.sort(key=lambda x:x.date)
        template_values['events'] = events
        template_values['num_found'] = len(events)
        template_values['radius'] = radius
        template_values['more_possible'] = (radius < 20)
        path = os.path.join(
            os.path.dirname(__file__), 'results.html')
        self.response.out.write(
            template.render(path, template_values))           

application = webapp.WSGIApplication(
                                     [('/', UserQuery),
                                      ('/findEvents', EventResults),
                                      ('/troubleshoot', Troubleshooter),
                                      ('/problem', ProblemReport),                                      
                                      ('/suggest', Suggestion),
                                      ('/suggestions', Suggestions),                                      
                                      ('/all', AllEvents),
                                      ('/clear', ClearEvents),],   
                                     debug=True)

def main():
    run_wsgi_app(application)

if __name__ == "__main__":
    main()